package com.aiwiown.snackmq.storage;

import com.aiwiown.snackmq.common.message.Message;
import com.aiwiown.snackmq.common.protocol.TopicPartition;

import java.io.IOException;
import java.util.List;

/**
 * 存储服务接口，已为分区和副本进行改造。
 * 所有操作现在都明确指定了目标分区，这是实现水平扩展的基石。
 */
public interface StorageService extends AutoCloseable {

    /**
     * 启动存储服务。
     * 对于分区化存储，这通常意味着准备好基础存储路径。
     *
     * @throws IOException 如果初始化失败
     */
    void start() throws IOException;

    /**
     * 【核心修复】: 定义一个接受 TopicPartition 和 offset 的 append 方法。
     * 这是所有存储服务实现都必须遵循的新契约。
     *
     * @param partition 目标分区
     * @param message   要追加的消息
     * @param offset    由 Raft 状态机决定的逻辑偏移量
     * @throws IOException 写入异常
     */
    void append(TopicPartition partition, Message message, long offset) throws IOException;
    /**
     * 【新增】批量追加消息到指定分区。
     * 这是为了优化状态机应用日志的性能，避免逐条追加。
     *
     * @param partition    目标分区
     * @param messages     要追加的消息列表
     * @param startOffset  此批次消息的起始逻辑位点
     * @param commitLogOffset 此批次在 Raft 日志中的物理位点 (physical offset)
     * @throws IOException 如果写入失败
     */
    void appendBatch(TopicPartition partition, List<Message> messages, long startOffset, long commitLogOffset) throws IOException;
    /**
     * 获取指定主题和分区的下一个可用偏移量。
     * 这是 offset 的唯一权威来源。
     *
     * @param topic       目标主题
     * @param partitionId 目标分区ID
     * @return 下一个可用的偏移量
     * @throws IOException 如果发生 I/O 错误
     */
    long getNextOffset(String topic, int partitionId) throws IOException;

    /**
     * 【新增】删除指定 Topic 的所有相关物理存储文件。
     *
     * @param topicName 要删除的 Topic 名称
     */
    void deleteTopic(String topicName);

    /**
     * 关闭存储服务并释放所有资源。
     * 这个方法现在正确地覆盖了 AutoCloseable.close()。
     *
     * @throws IOException 如果关闭失败
     */
    @Override
    void close() throws IOException;
}